﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataAccess;
using BussinessLogic.Models.Study;
using BussinessLogic.Models.Administrator;
using System.Data.Entity.Validation;
using System.Diagnostics;

namespace BussinessLogic.Services
{
    public class StudyServices
    {
        public static List<StudyPresentationModel> GetStudiesForPresentation(string username)
        {
            List<StudyPresentationModel> result = new List<StudyPresentationModel>();

            using (var bdContext = new LicentaEntities())
            {
                foreach (var study in bdContext.Studies.Where(s => s.Active))
                {
                    var studyPresentation = new StudyPresentationModel();
                    studyPresentation.ID = study.ID;
                    studyPresentation.Name = study.Name;
                    studyPresentation.Description = study.Description;
                    studyPresentation.InformedConsent = study.InformedConsent;
                    studyPresentation.Enrolled = study.UserStudies.Where(us => us.UserID == bdContext.Users.Where(u => u.Email == username).First().ID).FirstOrDefault() != null;
                    if (studyPresentation.Enrolled)
                    {
                        studyPresentation.Approved = study.UserStudies.Where(us => us.UserID == bdContext.Users.Where(u => u.Email == username).First().ID).First().IsApproved;
                    }

                    studyPresentation.Prerequisites = new List<StudyPrerequisitesModel>();
                    foreach (var prerequisite in study.Prerequisites)
                    {
                        studyPresentation.Prerequisites.Add(new StudyPrerequisitesModel { Name = prerequisite.Name, Description = prerequisite.Description });
                    }

                    result.Add(studyPresentation);
                }
            }

            return result;
        }


        public static bool ParticipateToStudy(string userName, int studyId)
        {
            using (var bdContext = new LicentaEntities())
            {
                bool userAlreadyRegistered = (from us in bdContext.UserStudies
                                              where (us.StudyID == studyId) && (us.User.Email == userName)
                                              select us).Count() != 0;

                if (userAlreadyRegistered)
                {
                    return false;
                }

                int userId = bdContext.Users.Where(u => u.Email == userName).FirstOrDefault().ID;

                UserStudy userStudy = new UserStudy { UserID = userId, StudyID = studyId, IsApproved = false };
                bdContext.UserStudies.Add(userStudy);

                bdContext.SaveChanges();
                return true;
            }
        }

        public static List<UserStudyApproveModel> GetUserStudyForApprove()
        {
            using (var bdContext = new LicentaEntities())
            {
                return (from us in bdContext.UserStudies
                        where !us.IsApproved
                        select new UserStudyApproveModel
                        {
                            StudyId = us.StudyID,
                            StudyName = us.Study.Name,
                            UserId = us.UserID,
                            UserName = us.User.FirstName + " " + us.User.LastName
                        }).OrderBy(p => p.UserName).ToList<UserStudyApproveModel>();

            }
        }

        public static bool ApproveUserToSudy(int studyId, int userId)
        {
            using (var bdContext = new LicentaEntities())
            {
                var userStudy = bdContext.UserStudies.Where(us => us.UserID == userId && us.StudyID == studyId).FirstOrDefault();

                if (userStudy == null)
                    return false;

                userStudy.IsApproved = true;

                bdContext.SaveChanges();

                return true;
            }
        }

        public static int CreateStudy(StudyCreateModel createStudy)
        {
            //TODO unique name
            using (var bdContext = new LicentaEntities())
            {
                Study study = new Study
                {
                    Name = createStudy.Name,
                    Description = createStudy.Description,
                    InformedConsent = createStudy.InformedConsent,
                    Active = createStudy.Active
                };

                bdContext.Studies.Add(study);
                bdContext.SaveChanges();

                return study.ID;
            }
        }

        public static List<StudyListItemModel> GetStudiesForMaintenance()
        {
            List<StudyListItemModel> result = new List<StudyListItemModel>();

            using (var bdContext = new LicentaEntities())
            {
                foreach (var study in bdContext.Studies)
                {
                    var studyPresentation = new StudyListItemModel
                    {
                        ID = study.ID,
                        Name = study.Name,
                        Description = study.Description,
                        Active = study.Active,
                        IsRunning = bdContext.Sessions.Where(s => s.StudyID == study.ID).FirstOrDefault() != null

                    };

                    result.Add(studyPresentation);
                }
            }

            return result;
        }

        public static bool DeleteStudy(int id)
        {
            using (var bdContext = new LicentaEntities())
            {
                var study = bdContext.Studies.Where(s => s.ID == id).FirstOrDefault();

                if (study == null)
                    return false;

                bdContext.Studies.Remove(study);
                bdContext.SaveChanges();
            }

            return true;
        }

        public static StudyCreateModel GetStudy(int id)
        {
            using (var bdContext = new LicentaEntities())
            {
                var study = bdContext.Studies.Where(s => s.ID == id).FirstOrDefault();

                if (study == null)
                    return null;

                StudyCreateModel studyModel = new StudyCreateModel
                {
                    Name = study.Name,
                    Description = study.Description,
                    InformedConsent = study.InformedConsent,
                    Active = study.Active
                };

                studyModel.Prerequisites = new List<StudyPrerequisitesModel>();
                foreach (var prerequisite in study.Prerequisites)
                {
                    studyModel.Prerequisites.Add(new StudyPrerequisitesModel { Name = prerequisite.Name, Description = prerequisite.Description });
                }

                return studyModel;
            }
        }

        public static void UpdateStudy(int id, StudyCreateModel model)
        {
            using (var bdContext = new LicentaEntities())
            {
                var study = bdContext.Studies.Where(s => s.ID == id).FirstOrDefault();

                if (study == null)
                    return;

                study.Active = model.Active;
                study.Name = model.Name;
                study.Description = model.Description;
                //study.Prerequisites = model.Prerequisites;
                study.InformedConsent = model.InformedConsent;

                bdContext.SaveChanges();
            }
        }



        public static Models.Study.StudyProtocol GetProtocolForStudy(int id)
        {
            using (var bdContext = new LicentaEntities())
            {
                var study = bdContext.Studies.Where(s => s.ID == id).FirstOrDefault();
                var protocol = study.StudyProtocols.FirstOrDefault();

                var result = new Models.Study.StudyProtocol() { StudyName = study.Name };
                result.Activities = new List<StudyExercise>();

                // add all existing exercises
                foreach (var activity in bdContext.Activities)
                {
                    result.Activities.Add(new StudyExercise
                    {
                        ID = activity.ID,
                        Name = activity.Name,
                        Repeat = 1
                    });
                }

                if (protocol == null)
                {
                    return result;
                }

                result.StudyName = protocol.Study.Name;
                result.IsRunning = bdContext.Sessions.Where(s => s.StudyID == id).FirstOrDefault() != null;

                result.Groups = new List<GroupStudy>();



                // add groups for protocol
                foreach (var group in protocol.StudyProtocolGroups.OrderBy(p => p.Sequence))
                {
                    var groupStudy = new GroupStudy
                    {
                        Name = group.Name,
                        Repeat = group.Repeat
                    };

                    groupStudy.Sessions = new List<StudySession>();

                    //add sessions for group
                    foreach (var session in group.StudyProtocolSessions.OrderBy(s => s.Sequence))
                    {
                        var sessionStudy = new StudySession
                        {
                            Name = session.Name,
                            Repeat = session.Repeat,
                        };
                        sessionStudy.Exercises = new List<StudyExercise>();

                        //add exercises for session
                        foreach (var activity in session.StudyProtocolExercises.OrderBy(a => a.Sequence))
                        {
                            var activityStudy = new StudyExercise
                            {
                                ID = activity.ActivityID,
                                Name = activity.Activity.Name,
                                Repeat = activity.Repeat
                            };
                            sessionStudy.Exercises.Add(activityStudy);
                        }

                        groupStudy.Sessions.Add(sessionStudy);
                    }
                    result.Groups.Add(groupStudy);
                }

                return result;
            }
        }

        public static List<Exercise.ExerciseListItemModel> GetAllActivities()
        {
            using (var bdContext = new LicentaEntities())
            {
                var activities = new List<Exercise.ExerciseListItemModel>();
                foreach (var activity in bdContext.Activities)
                {
                    var ac = new Exercise.ExerciseListItemModel
                    {
                        ID = activity.ID,
                        Name = activity.Name,
                        Description = activity.Description,
                        Type = (ActivityType)activity.ActivityType,
                        IsRunning = bdContext.SessionActivityResults.Where(ar => ar.ActivityID == activity.ID).FirstOrDefault() != null
                    };

                    activities.Add(ac);
                }
                return activities;
            }
        }

        public static int CreateActivity(Exercise.CreateExercise model)
        {
            //TODO unique name
            using (var bdContext = new LicentaEntities())
            {
                var activity = bdContext.Activities.Where(a => a.ID == model.ID).FirstOrDefault();
                if (activity == null)
                {
                    activity = new Activity();

                    activity.Name = model.Name;
                    activity.Description = model.Description;
                    activity.ActivityType = (int)model.ExerciseType;

                    bdContext.Activities.Add(activity);
                    bdContext.SaveChanges();
                }
                else
                {
                    activity.Name = model.Name;
                    activity.Description = model.Description;
                    activity.ActivityType = (int)model.ExerciseType;


                    bdContext.SaveChanges();
                }




                return activity.ID;
            }
        }

        public static bool DeleteActivity(int id)
        {
            using (var bdContext = new LicentaEntities())
            {
                var activity = bdContext.Activities.Where(a => a.ID == id).FirstOrDefault();

                if (activity == null)
                    return false;

                bdContext.Activities.Remove(activity);
                bdContext.SaveChanges();
            }

            return true;
        }

        public static Models.QuestionnaireMaintenance GetQuestionnaire(int id)
        {
            using (var bdContext = new LicentaEntities())
            {
                var questionnaire = bdContext.ActivityQNs.Where(qn => qn.ID == id).FirstOrDefault();

                if (questionnaire == null)
                {
                    return null;
                }

                Models.QuestionnaireMaintenance result = new Models.QuestionnaireMaintenance();
                result.Questions = new List<Models.Question>();
                result.IsRunning = bdContext.Sessions.Where(s => s.SessionActivityResults.Where( sr => sr.ActivityType == (int)ActivityType.Questionnaire && sr.ActivityID == id).FirstOrDefault() != null).FirstOrDefault() != null;
                result.Name = questionnaire.Activity.Name;


                foreach (var question in questionnaire.ActivityQNQuestions.OrderBy(q => q.Sequence))
                {
                    var qn = new Models.Question
                    {
                        Text = question.Text,
                        HasFreeAnswer = question.FreeTextAnswer,
                        HasMultipleChoice = question.MultipleChoise
                    };
                    qn.Answers = new List<Models.QMultiChoiceAnswer>();

                    foreach (var answer in question.ActivityQNAnswers.OrderBy(q => q.Sequence))
                    {
                        qn.Answers.Add(new Models.QMultiChoiceAnswer
                        {
                            Text = answer.Text,
                            Value = answer.Value
                        });
                    }

                    result.Questions.Add(qn);
                }

                return result;
            }
        }

        public static void SaveQuestionnaire(Models.QuestionnaireMaintenance protocol)
        {
            using (var bdContext = new LicentaEntities())
            {
                ActivityQN qn = bdContext.ActivityQNs.Where(q => q.ID == protocol.ID).FirstOrDefault();
                if (qn != null)
                {
                    bdContext.ActivityQNs.Remove(qn);
                    bdContext.SaveChanges();
                }

                qn = new ActivityQN();
                qn.ID = protocol.ID;

                int i = 0;
                foreach (var pQuestion in protocol.Questions)
                {
                    ActivityQNQuestion question = new ActivityQNQuestion
                    {
                        Text = pQuestion.Text,
                        Sequence = i++,
                        MultipleChoise = pQuestion.HasMultipleChoice,
                        FreeTextAnswer = pQuestion.HasFreeAnswer,
                        ActivityQN = qn
                    };
                    int j = 0;
                    foreach (var pAnswer in pQuestion.Answers)
                    {
                        ActivityQNAnswer answer = new ActivityQNAnswer
                        {
                            Text = pAnswer.Text,
                            Value = pAnswer.Value,
                            Sequence = j++,
                            FreeAnswer = pQuestion.HasFreeAnswer,
                            ActivityQNQuestion = question
                        };
                        question.ActivityQNAnswers.Add(answer);
                    }
                    qn.ActivityQNQuestions.Add(question);
                }

                qn.Activity = bdContext.Activities.Where(a => a.ID == protocol.ID).FirstOrDefault();

                bdContext.ActivityQNs.Add(qn);
                bdContext.SaveChanges();
            }
        }

        public static void SaveProtocol(Models.Study.StudyProtocol protocol)
        {
            using (var bdContext = new LicentaEntities())
            {
                var bdProtocol = bdContext.StudyProtocols.Where(s => s.StudyID == protocol.StudyID).FirstOrDefault();
                if (bdProtocol != null)
                {
                    bdContext.StudyProtocols.Remove(bdProtocol);
                    bdContext.SaveChanges();
                }

                bdProtocol = new DataAccess.StudyProtocol();
                bdProtocol.StudyID = protocol.StudyID;

                int i = 0;
                foreach (var g in protocol.Groups)
                {
                    var group = new StudyProtocolGroup
                    {
                        Name = g.Name,
                        Repeat = g.Repeat,
                        Sequence = i,
                        StudyProtocol = bdProtocol,
                        IsForApproval = i++ == 0
                    };

                    int j = 0;
                    foreach (var s in g.Sessions)
                    {
                        var session = new StudyProtocolSession
                        {
                            Name = s.Name,
                            Sequence = j++,
                            Repeat = s.Repeat,
                            StudyProtocolGroup = group
                        };

                        int k = 0;
                        foreach (var e in s.Exercises)
                        {
                            var exercise = new StudyProtocolExercis
                            {
                                ActivityID = e.ID,
                                Repeat = e.Repeat,
                                Sequence = k++,
                                StudyProtocolSession = session
                            };
                            session.StudyProtocolExercises.Add(exercise);
                        }
                        group.StudyProtocolSessions.Add(session);
                    }
                    bdProtocol.StudyProtocolGroups.Add(group);
                }
                bdProtocol.Study = bdContext.Studies.Where(s => s.ID == protocol.StudyID).FirstOrDefault();

                bdContext.StudyProtocols.Add(bdProtocol);
                bdContext.SaveChanges();
            }
        }

        public static void SaveExercise(Exercise.ExerciseMaintain em)
        {
            using (var bdContext = new LicentaEntities())
            {
                var exercise = bdContext.ActivityExercises.Where(e => e.ID == em.ID).FirstOrDefault();
                if (exercise != null)
                {
                    bdContext.ActivityExercises.Remove(exercise);
                    bdContext.SaveChanges();
                }

                exercise = new ActivityExercise
                {
                    PictureTimeout = em.PictureTime,
                    NumberTimeout = em.CrossNumberTime,
                    AcomodationTrials = em.BaselineTrials,
                    FinalSession = em.FinalSession,
                    FixationTrials = em.FixationTrials
                };

                foreach (var picture in em.NegativePhotos)
                {
                    var nPhoto = new ActivityExercisePicture
                    {
                        ActivityExercise = exercise,
                        PictureName = picture,
                        Type = (int)PictureType.Negative
                    };
                    exercise.ActivityExercisePictures.Add(nPhoto);
                }

                foreach (var picture in em.NeutralPhotos)
                {
                    var nPhoto = new ActivityExercisePicture
                    {
                        ActivityExercise = exercise,
                        PictureName = picture,
                        Type = (int)PictureType.Neutral
                    };
                    exercise.ActivityExercisePictures.Add(nPhoto);
                }

                foreach (var ctrial in em.Trials)
                {
                    var trial = new ActivityExerciseCustomTrial
                    {
                        Letter = (int)ctrial.Letter,
                        LetterPosition = (int)ctrial.LetterPosition,
                        NeutralPosition = (int)ctrial.NeutralPosition,
                        ActivityExercise = exercise,
                        Repeat = ctrial.Repeat
                    };
                    exercise.ActivityExerciseCustomTrials.Add(trial);
                }

                exercise.Activity = bdContext.Activities.Where(a => a.ID == em.ID).FirstOrDefault();

                bdContext.ActivityExercises.Add(exercise);
                bdContext.SaveChanges();
            }
        }

        public static Exercise.CreateExercise GetExercise(int id)
        {
            using (var bdContext = new LicentaEntities())
            {
                var exercise = bdContext.Activities.Where(a => a.ID == id).FirstOrDefault();
                if (exercise == null)
                {
                    return null;
                }

                var result = new Exercise.CreateExercise()
                {
                    Name = exercise.Name,
                    Description = exercise.Description,
                    ExerciseType = exercise.ActivityType,
                    IsRunning = bdContext.SessionActivityResults.Where(ar => ar.ActivityID == id).FirstOrDefault() != null
                };

                return result;
            }
        }

        public static Exercise.ExerciseMaintain GetExerciseProtocol(int id)
        {
            using (var bdContext = new LicentaEntities())
            {
                var ex = bdContext.ActivityExercises.Where(a => a.ID == id).FirstOrDefault();
                if (ex == null)
                {
                    return null;
                }


                Exercise.ExerciseMaintain result = new Exercise.ExerciseMaintain
                {
                    FinalSession = ex.FinalSession,
                    BaselineTrials = ex.AcomodationTrials,
                    CrossNumberTime = ex.NumberTimeout,
                    PictureTime = ex.PictureTimeout,
                    FixationTrials = ex.FixationTrials,
                    IsRunning = bdContext.SessionActivityResults.Where(ar => ar.ActivityID == id).FirstOrDefault() != null
                };
                result.SavedNegativePhotos = new List<string>();
                result.SavedNeutralPhotos = new List<string>();

                foreach (var pic in ex.ActivityExercisePictures)
                {
                    if (pic.Type == (int)PictureType.Neutral)
                    {
                        result.SavedNeutralPhotos.Add(pic.PictureName);
                    }
                    else
                    {
                        result.SavedNegativePhotos.Add(pic.PictureName);
                    }
                }

                result.SavedTrials = new List<Exercise.ExerciseTrial>();

                foreach (var custom in ex.ActivityExerciseCustomTrials)
                {
                    result.SavedTrials.Add(new Exercise.ExerciseTrial
                    {
                        Letter = (Exercise.ExerciseTrial.LetterType)custom.Letter,
                        NeutralPosition = (Exercise.ExerciseTrial.Position)custom.NeutralPosition,
                        LetterPosition = (Exercise.ExerciseTrial.Position)custom.LetterPosition,
                        Repeat = custom.Repeat
                    });
                }

                return result;
            }
        }

        public static Exercise.MatrixExerciseMaintain GetMatrixExerciseProtocol(int id)
        {
            using (var bdContext = new LicentaEntities())
            {
                var ex = bdContext.ActivityMatrixExercises.Where(a => a.ID == id).FirstOrDefault();
                if (ex == null)
                {
                    return null;
                }

                Exercise.MatrixExerciseMaintain result = new Exercise.MatrixExerciseMaintain
                {
                    TrialsCount = ex.TrialCount,
                    IsRunning = bdContext.Sessions.Where(s => s.SessionActivityResults.Where(sr => sr.ActivityType == (int)ActivityType.MatrixExercise).FirstOrDefault() != null).FirstOrDefault() != null
                };

                result.SavedNegativePhotos = new List<string>();
                result.SavedNeutralPhotos = new List<string>();

                foreach (var pic in ex.ActivityMatrixExercisePictures)
                {
                    if (pic.Type == (int)PictureType.Neutral)
                    {
                        result.SavedNeutralPhotos.Add(pic.PictureName);
                    }
                    else
                    {
                        result.SavedNegativePhotos.Add(pic.PictureName);
                    }
                }

                return result;
            }
        }

        public static void SaveMatrixExercise(Exercise.MatrixExerciseMaintain em)
        {
            using (var bdContext = new LicentaEntities())
            {
                var exercise = bdContext.ActivityMatrixExercises.Where(e => e.ID == em.ID).FirstOrDefault();
                if (exercise != null)
                {
                    bdContext.ActivityMatrixExercises.Remove(exercise);
                    bdContext.SaveChanges();
                }

                exercise = new ActivityMatrixExercis
                {
                    TrialCount = em.TrialsCount
                };

                foreach (var picture in em.NegativePhotos)
                {
                    var nPhoto = new ActivityMatrixExercisePicture
                    {
                        ActivityMatrixExercis = exercise,
                        PictureName = picture,
                        Type = (int)PictureType.Negative
                    };
                    exercise.ActivityMatrixExercisePictures.Add(nPhoto);
                }

                foreach (var picture in em.NeutralPhotos)
                {
                    var nPhoto = new ActivityMatrixExercisePicture
                    {
                        ActivityMatrixExercis = exercise,
                        PictureName = picture,
                        Type = (int)PictureType.Neutral
                    };
                    exercise.ActivityMatrixExercisePictures.Add(nPhoto);
                }


                exercise.Activity = bdContext.Activities.Where(a => a.ID == em.ID).FirstOrDefault();

                bdContext.ActivityMatrixExercises.Add(exercise);
                bdContext.SaveChanges();
            }
        }
    }
}
